/**
 * 在这里定义与用户相关的路由处理函数，供/router/user.js模块使用
 */

// 导入db模块
const db = require('../db/index')
// 导入bcryptjs处理密码的模块
const bcrypt = require('bcryptjs')
// 用这个包来生成Token字符串
const jwt = require('jsonwebtoken')
// 导入全局的配置文件
const config = require('../config') 

// 注册用户的处理函数
exports.register = (req, res) => {
  // 1. 检测表单数据是否合法
  // 获取客户端提交到服务器上的用户信息
  const userInfo = req.body
  // 检测用户名是否被占用
  // 定义SQL语句，查询用户名是否被占用
  const sqlStr = 'select * from user where username=?'
  // 执行SQL语句
  db.query(sqlStr, [userInfo.username], (err, results1) => {
    if (err) {
      return res.status(500).json({ status: 500, message: err.message })
    }
    // 未出错，判断用户名是否被占用
    if (results1.length > 0) {
      return res.status(400).json({ status: 400, message: '用户名被占用，请更换其他用户名' })
    }

    // 判断邮箱是否被占用
    const sqlEmail = 'select * from user where email=?'
    db.query(sqlEmail, [userInfo.email], (err, results2) => {
      if (err) {
        return res.status(500).json({ status: 500, message: err.message })
      }
      // 未出错，判断邮箱是否被占用
      if (results2.length > 0) {
        return res.status(400).json({ status: 400, message: '该邮箱已经注册过账号，请更换其他邮箱号' })
      }

      // 4. 对密码进行加密
      // 使用bcrypt包，优点：① 无法逆向破解  ② 同一明文密码加密，得到的加密结果各不相同
      // 先调用bcrypt.hashSync(明文密码, 随机盐的长度) 方法对密码进行加密
      userInfo.password = bcrypt.hashSync(userInfo.password, 10)

      // 5. 插入新用户
      // 定义插入新用户的sql语句
      const sqlZhuCe = 'insert into user set ?'
      // 调用db.query()执行sql语句
      db.query(sqlZhuCe,
        { username: userInfo.username, password: userInfo.password, email: userInfo.email },
        (err, results3) => {
                  // 判断是否成功
        if (err) {
          return res.status(500).json({ status: 500, message: err.message })
        }
        // 判断影响行数是否为1 => 防止同一时间同一个用户名被多个人注册
        if (results3.affectedRows !== 1) {
          return res.status(500).json({ status: 500, message: '注册用户失败，请稍后重试' })
        }
        // 注册用户成功
        res.status(200).json({ status: 200, message: '注册成功' })
        }
      )
    })
  })
}

// 用户登录的处理函数
exports.login = (req, res) => {
  // 接收表单数据
  const userInfo = req.body
  console.log(userInfo)
  // 查询用户信息
  const sqlStr_name = 'select * from user where username=?'
  db.query(sqlStr_name, [userInfo.username], (err, results) => {
    if (err) {
      return res.status(500).json({ code: 500, message: err.message })
    }
    // 执行sql语句成功，但是获取的条数不等于1
    if (results.length === 0) {
      return res.status(400).json({ code: 400, message: '该用户不存在' })
    }
    // 判断密码是否正确
    const cmpresult = bcrypt.compareSync(userInfo.password, results[0].password)
    if (!cmpresult) {
      return res.status(400).json({ code: 400, message: '密码错误' })
    }
    // 在服务器端生成Token字符串
    const user = { ...results[0] }
    // 生成accessToken
    const accessToken = jwt.sign(
      { id: user.id, username: user.username, phone: user.phone, email: user.email },
      config.jwtSecretKey,
      { expiresIn: config.accessExpiresIn }
    )
    // 生成refreshToken
    const refreshToken = jwt.sign(
      { id: user.id, username: user.username, phone: user.phone, email: user.email },
      config.refreshTokenSecretKey,
      { expiresIn: config.refreshExpiresIn }
    )
    // 将refreshToken存储到数据库中
    const expiresAt = new Date()
    expiresAt.setSeconds(expiresAt.getSeconds() + config.refreshExpiresInSec)
    const sqlStr_refreshToken = 'update user set refresh_token=?, expires_at=? where id=?'
    db.query(sqlStr_refreshToken, [refreshToken, expiresAt, user.id], (err) => {
      if (err) {
        console.error('保存refreshToken失败:', err)
        return res.status(500).json({ code: 500, message: '保存refreshToken失败' })
      }
      // 设置cookie
      res.cookie('token', accessToken, {
        maxAge: config.accessExpiresInSec * 1000,
        httpOnly: true,
        secure: false, // 开发环境使用HTTP，设为false
        path: '/'
      })
      res.cookie('refresh_token', refreshToken, {
        maxAge: config.refreshExpiresInSec * 1000,
        httpOnly: true,
        secure: false, // 开发环境使用HTTP，设为false
        path: '/',
        sameSite: 'lax' // 开发环境使用lax
      })
      res.status(200).json({
        code: 200,
        message: '登录成功',
        data: {
          userInfo: {
            userId: results[0].id,
            username: results[0].username,
            phone: results[0].phone,
            email: results[0].email,
            avatar: results[0].avatar
          },
          token: accessToken
        }
      })
    })  
  })
}

// 退出登录
exports.logout = (req, res) => {
  // 从cookie获取refreshToken
  const refreshToken = req.cookies.refresh_token
  // 判断refreshToken是否存在
  if (!refreshToken) {
    return res.status(400).json({ code: 400, message: '缺少refreshToken，请先登录' })
  }

  try {
    // 解析refreshToken获取用户信息
    const decoded = jwt.verify(refreshToken, config.refreshTokenSecretKey)
    
    // 清除数据库中的refresh_token和expires_at
    const sqlStr = 'UPDATE user SET refresh_token = NULL, expires_at = NULL WHERE id = ?'
    db.query(sqlStr, [decoded.id], (err, results) => {
      if (err) {
        console.error('清除数据库token失败:', err)
        return res.status(500).json({ code: 500, message: '退出登录失败' })
      }

      // 清除cookie中的token
      res.clearCookie('token', {
        httpOnly: true,
        secure: false,
        path: '/'
      })
      
      // 清除cookie中的refresh_token
      res.clearCookie('refresh_token', {
        httpOnly: true,
        secure: false,
        path: '/',
        sameSite: 'lax'
      })

      res.status(200).json({ code: 200, message: '退出登录成功' })
    })
  } catch (err) {
    // 如果refreshToken无效或过期，直接清除cookie
    res.clearCookie('token', {
      httpOnly: true,
      secure: false,
      path: '/'
    })
    
    res.clearCookie('refresh_token', {
      httpOnly: true,
      secure: false,
      path: '/',
      sameSite: 'lax'
    })

    res.status(200).json({ code: 200, message: '退出登录成功' })
  }
}